package com.skyline.energy.provider.ehcache;

import java.util.Set;

import net.sf.ehcache.bootstrap.BootstrapCacheLoader;
import net.sf.ehcache.event.CacheEventListener;
import net.sf.ehcache.store.MemoryStoreEvictionPolicy;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.InitializingBean;

import com.skyline.energy.cache.Cache;
import com.skyline.energy.cache.CacheManager;
import com.skyline.energy.exception.CacheUnreachableException;

public class EhcacheManager implements CacheManager, InitializingBean {
	private static final Log LOGGER = LogFactory.getLog(EhcacheManager.class);
	net.sf.ehcache.CacheManager cacheManager;

	private int maxElementsInMemory = 10000;

	private MemoryStoreEvictionPolicy memoryStoreEvictionPolicy = MemoryStoreEvictionPolicy.LRU;

	private boolean overflowToDisk = true;

	private boolean eternal = false;

	private int timeToLive = 120;

	private int timeToIdle = 120;

	private boolean diskPersistent = false;

	private int diskExpiryThreadIntervalSeconds = 120;

	private BootstrapCacheLoader bootstrapCacheLoader;

	private Set<CacheEventListener> cacheEventListeners;

	public void setCacheManager(net.sf.ehcache.CacheManager cacheManager) {
		this.cacheManager = cacheManager;
	}

	@Override
	public Cache getCache(String pool) {
		net.sf.ehcache.Cache cache = null;
		try {
			cache = doGetCache(pool.toUpperCase());
		} catch (Exception e) {
			throw new CacheUnreachableException("Can't create Ehcache Instance");
		}
		Ehcache ehcache = new Ehcache();
		ehcache.setCache(cache);
		return ehcache;
	}

	private net.sf.ehcache.Cache doGetCache(String cacheName) {
		net.sf.ehcache.Cache rawCache;
		if (this.cacheManager.cacheExists(cacheName)) {
			if (LOGGER.isDebugEnabled()) {
				LOGGER.debug("Using existing EHCache cache region '" + cacheName + "'");
			}
			rawCache = this.cacheManager.getCache(cacheName);
		} else {
			if (LOGGER.isDebugEnabled()) {
				LOGGER.debug("Creating new EHCache cache region '" + cacheName + "'");
			}
			rawCache = createCache(cacheName);
			this.cacheManager.addCache(rawCache);
		}

		return rawCache;
	}

	private net.sf.ehcache.Cache createCache(String cacheName) {
		net.sf.ehcache.Cache cache = new net.sf.ehcache.Cache(cacheName, maxElementsInMemory,
				memoryStoreEvictionPolicy, overflowToDisk, null, eternal, timeToLive, timeToIdle, diskPersistent,
				diskExpiryThreadIntervalSeconds, null, bootstrapCacheLoader);

		if (this.cacheEventListeners != null) {
			for (CacheEventListener listener : this.cacheEventListeners) {
				cache.getCacheEventNotificationService().registerListener(listener);
			}
		}
		return cache;

	}

	@Override
	public void afterPropertiesSet() throws Exception {
		if (this.cacheManager == null) {
			if (LOGGER.isDebugEnabled()) {
				LOGGER.debug("Using default EHCache CacheManager");
			}
			this.cacheManager = net.sf.ehcache.CacheManager.getInstance();
		}

	}

}
